home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume4 / sco-crash < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  34.8 KB

  1. Path: xanth!mcnc!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
  2. From: jfh@rpp386.UUCP (The Beach Bum)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i020: /etc/crash utility for SCO Xenix 2.2.1
  5. Message-ID: <8808111148.AA12910@rpp386.UUCP>
  6. Date: 11 Aug 88 16:48:27 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: jfh@rpp386.UUCP (The Beach Bum)
  9. Lines: 1539
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 4, Issue 20
  13. Submitted-by: "The Beach Bum" <jfh@rpp386.UUCP>
  14. Archive-name: sco-crash
  15.  
  16. This is the initial release of my SCO Xenix crash utility.  It is intended
  17. to replace the crash(1) command which SCO did not include.
  18.  
  19. This command is known to run on only SCO Xenix 2.2.1.  The only parts which
  20. should need adjustment for most reasonable UNIX(R) systems are the user
  21. page and process table entry routines.  A Plexus System V port is in the
  22. works for you and should be available Real Soon Now ;-)
  23.  
  24. [Plexus System III and System V both have working crash utilities.  ++bsa]
  25.  
  26. - John.
  27. --
  28. #! /bin/sh
  29. # This is a shell archive, meaning:
  30. # 1. Remove everything above the #! /bin/sh line.
  31. # 2. Save the resulting text in a file.
  32. # 3. Execute the file with /bin/sh (not csh) to create:
  33. #    README
  34. #    Makefile
  35. #    crash.c
  36. #    interact.c
  37. #    files.c
  38. #    inodes.c
  39. #    mounts.c
  40. #    procs.c
  41. #    texts.c
  42. #    user.c
  43. #    vars.c
  44. #    stats.c
  45. #    bufs.c
  46. #    crash.h
  47. # This archive created: Thu Aug 11 11:45:59 1988
  48. # By:    The Beach Bum (HASA, "S" Division)
  49. export PATH; PATH=/bin:/usr/bin:$PATH
  50. if test -f 'README'
  51. then
  52.     echo shar: "will not over-write existing file 'README'"
  53. else
  54. cat << \SHAR_EOF > 'README'
  55. crash(1L)                       Version 1.0                     08/11/88
  56.  
  57. Introduction
  58.  
  59. Crash is a utility for examining kernel tables while the system is
  60. running, or if there is a facility for taking crash dumps, examining the
  61. system after it has crashed.  SCO does not provide a crash dump facility
  62. at this time, so that functionality is not present.
  63.  
  64. The kernel structures which can be examined at present are:
  65.  
  66.     block buffer headers
  67.     open file table entries
  68.     active inode table entries
  69.     mounted file system table entries
  70.     process table entries
  71.     system statistics such as name, version, age
  72.     active and sticky bit text table entries
  73.     per process user page information
  74.     tunable parameters
  75.  
  76. Using this information, it is possible to determine what files a given
  77. process is using, what device they reside on, who owns them and where
  78. the file pointer is currently positioned.  Other information on running
  79. processes may also be determined.
  80.  
  81. This version of crash differs from most other versions, such as that
  82. produced by AT&T for their UNIX(tm) systems, in that swapped user pages
  83. may be printed and the name for swapped processes is given.  Also, not
  84. all of the aliases which are listed in the manual page from AT&T are
  85. provided.  A number of commands have been left out, and some of the
  86. options for the included commands have been omitted as well.
  87.  
  88. Commands
  89.  
  90. Most commands take a list of table entries, which if not present
  91. defaults to all elements in the table.
  92.  
  93. Print Buffer Headers
  94. Syntax:    buf, b
  95.  
  96. Prints the selected block buffer headers.
  97.  
  98. Example:
  99. > buf 0 1 2 3 4
  100.  BUF MAJ  MIN    BLOCK FLAGS
  101.    0 001 0047    20925 read done
  102.    1 001 0037     2817 read done
  103.    2 001 0050     2801 read done
  104.    3 001 0037    15175 read done
  105.    4 001 0050        6 done
  106.  
  107. Print Open File Table Entries
  108. Syntax: file, f
  109.  
  110. Prints the selected open file table entries, with cross references
  111. to the associated inodes, and the current file pointer.
  112.  
  113. Example:
  114. > file 0 1 2 3 4
  115. SLOT    FLAG          COUNT  INODE      OFFSET
  116.    0    001 R             1      9           0
  117.    1    003 RW            3      3          18
  118.    2    003 RW            7     11       26800
  119.    3    002  W            2      4         169
  120.    4    001 R             1      8           0
  121.  
  122. Display Command Summary
  123. Syntax: help, h, ?
  124.  
  125. Prints the list of currently available commands and the aliases
  126. for them.
  127.  
  128. Example:
  129. > help
  130. command summary
  131.  
  132. buf (b)        - buffer headers
  133. file (f)       - open files
  134. help (h,?)     - list commands
  135. inode (ino,i)  - active inodes
  136. mount (m)      - mounted file systems
  137. proc (p)       - active and defunct processes
  138. quit (q,^D)    - exit crash
  139. stat (s)       - crash statistics, age, time
  140. text (t)       - active and sticky bit text segments
  141. user (u)       - user page information
  142. var (v)        - tunable parameters
  143.  
  144. Display Active Inode Table Entries
  145. Syntax: inode, ino, i
  146.  
  147. Prints selected active inode table entries giving device, file
  148. size, permissions, and owners.  Cross referenced from mount and
  149. file tables.
  150.  
  151. Example:
  152. > inode 0 2 6 8 20
  153. SLOT MAJ  MIN INUMB REF LINK  UID  GID     SIZE    MODE SMAJ SMIN FLAGS
  154.    0 001 0050     2   5   13    0    0      464 d---755    -    -
  155.    2 001 0050    44   1    1    3    3    13472 f---700    -    - txt
  156.    6 001 0050   204   1    2    0    0       32 d---777    -    - mnt
  157.    8 001 0050    87   2    1   10   10        0 c---666 0004 0002
  158.   20 001 0050   471   1    1    3    3    50102 f---711    -    - acc txt
  159.  
  160. Display Mounted File System Table Entries
  161. Syntax: mount, m
  162.  
  163. Prints the system entries for mounted on file systems.  The
  164. device, mount point, file system sizes and free blocks and inodes
  165. are displayed.
  166.  
  167. Example:
  168. > mount
  169. SLOT  MAJ  MIN  INODE  BUF  VOLUME  PACK   BLOCKS INODES  BFREE  IFREE
  170.    0    1  050      0   10                   7163   1808   1237   1251
  171.    1    1  037      6  230  usr     rpp386  34000  17024   1320  14238
  172.    2    1  047      7  245                  22950  15024   5499   9800
  173.    3    2  064     23  387                   1200    320    210     50
  174.  
  175. Display Process Table Entries
  176. Syntax: proc, p
  177.  
  178. Prints selected running and defunct process information.  The process
  179. ids, user ids, CPU usage, scheduling priority and wait event are
  180. displayed.  The process name is determined by locating the user page.
  181.  
  182. Example:
  183. > proc 0 1 2 3 4
  184. SLT ST  PID  PPID  PGRP   UID  EUID PRI CPU    EVENT NAME       FLAGS
  185.   0 s     0     0     0     0     0   0  15    16c5c swapper    incore sched
  186.   1 s     1     0     0     0     0  30   0     eeac init       incore text
  187.   2 s  9389     1  9389   100   100  30   0     ef54 csh        incore text
  188.   3 s    31     1     0     0     0  26   0     5eac logger     swapped
  189.   4 s    30     1     0     0     0  40   0  6000000 update     incore text
  190.  
  191. Exit Crash Command
  192. Syntax: quit, q, ^D
  193.  
  194. Exits Crash.
  195.  
  196. Example:
  197. > quit
  198. $
  199.  
  200. Print System Statics
  201. Syntax: stat, s
  202.  
  203. Prints information regarding system name, operating system release, version,
  204. date of crash, and uptime at time of crash.
  205.  
  206. Example:
  207. > stat
  208.     sysname: XENIX
  209.     nodename: rpp386
  210.     release: 2.2.1
  211.     version: SysV
  212.     machine: i80386
  213.     time of crash: Thu Aug 11 11:18:00 1988
  214.     age of system: 35 days, 23 hrs., 7 mins.
  215.  
  216. Print Text Table Entries
  217. Syntax: text, t
  218.  
  219. Prints current text table entries.  Cross references to inode number
  220. and process table entry and gives the number of processes which are
  221. currently referencing this table entry.
  222. Example:
  223. > text 0 1 2 3 4
  224. SLOT  INODE  REF  LDREF  PROC  SWAPLO+   SIZE  FLAGS
  225.    0      2    1      1     1        0      0  write
  226.    1     20    2      1     9        0      0  write
  227.    2      5    1      1     4        0      0  write
  228.    3     10    1      0     0        0      0  write
  229.    4     21    1      1    10        0      0  write
  230.  
  231. Print Per Process User Page Information
  232. Syntax: user, u
  233.  
  234. Prints the user page for the current process or a group of processes.
  235. The argument is the process table slot.  If omitted, the currently
  236. running process, which will invariably be crash, user page will be
  237. displayed.  Information includes user and system times, user and
  238. group ids, file I/O, system accounting and open file information.
  239. Provides a list of currently open files by file table entry number.
  240.  
  241. Example:
  242. > user
  243. PER PROCESS USER AREA:
  244. USER ID's:    uid: 100, gid: 0, real uid: 100, real gid: 0
  245. PROCESS TIMES:    user: 16, sys: 22, child user: 0, child sys: 0
  246. PROCESS MISC:    proc slot: 10, cntrl tty: maj(0) min(0)
  247. IPC:        locks: unlocked
  248. FILE I/O:    user addr: 25703640, file offset: 100665344, bytes: 1892,
  249.         segment: user, umask: 22, ulimit: 2097152
  250. ACCOUNTING:    command: crash, memory: 1987167, type: exec
  251.         start: Thu Aug 11 11:28:10 1988
  252. OPEN FILES:    file desc:     0   1   2   3   4   5
  253.         file slot:    11  13  13  18  19  20
  254.  
  255. Print Tunable Parameter Information
  256. Syntax: var, v
  257.  
  258. Displays the tunable parameter values which were used at the time
  259. of system generation.  Included are number of open files, processes
  260. per user, inodes, mounts, pure text entries and other related
  261. information.
  262.  
  263. Example:
  264. > var
  265. buffers      512
  266. calls       30
  267. inodes      100
  268. e_inodes  100
  269. files      100
  270. e_files      100
  271. mounts        8
  272. e_mounts    8
  273. procs       60
  274. e_procs       16
  275. texts       40
  276. e_texts       40
  277. clists       64
  278. sabufs       64
  279. maxproc       30
  280. hashbuf      512
  281. hashmask  511
  282.  
  283. Caveats and Features
  284.  
  285. This release of crash is known to run under SCO Xenix 2.2.1.  No other
  286. ports are presently known of.  For the most part, porting to a different
  287. release of Xenix should be quite painless.  The principle changes are
  288. likely to be in the user area and process table entries.
  289.  
  290. None of the options are presently implemented.  Commands which have been
  291. implemented have only one format.
  292.  
  293. All of the commands are available as command line options.  Use the one
  294. letter command alias as the command line option.  The output defaults
  295. to what it would be if that one letter alias were issued to crash as a
  296. command.  Multiple flags may be given.  When in doubt, read the source.
  297. SHAR_EOF
  298. fi
  299. if test -f 'Makefile'
  300. then
  301.     echo shar: "will not over-write existing file 'Makefile'"
  302. else
  303. cat << \SHAR_EOF > 'Makefile'
  304. # Your favorite Bourne Shell and Mine ...
  305. SHELL=/bin/sh
  306. # A list of all object files which need to be made
  307. OBJS =    crash.o interact.o files.o inodes.o mounts.o procs.o texts.o \
  308.     user.o vars.o stats.o bufs.o
  309. # A list of C files and such for sharchiving
  310. FILES =    README Makefile \
  311.     crash.c interact.c files.c inodes.c mounts.c procs.c texts.c \
  312.     user.c vars.c stats.c bufs.c crash.h
  313. # C flags, suitable for debugging or production.
  314. CFLAGS = -c -Ox -g
  315.  
  316. crash:    $(OBJS)
  317.     cc -o crash -g $(OBJS)
  318.  
  319. clean:
  320.     rm -f *.o a.out
  321.  
  322. clobber:    clean
  323.     rm -f crash core
  324.  
  325. shar:    $(FILES)
  326.     shar $(FILES) > crash.shar
  327.  
  328. crash.o:    crash.h crash.c
  329.  
  330. interact.o:    interact.c
  331.  
  332. files.o:    crash.h files.c
  333.  
  334. inodes.o:    crash.h inodes.c
  335.  
  336. mounts.o:    crash.h mounts.c
  337.  
  338. procs.o:    crash.h procs.c
  339.  
  340. stats.o:    crash.h stats.c
  341.  
  342. texts.o:    crash.h texts.c
  343.  
  344. user.o:    crash.h user.c
  345.  
  346. vars.o:    crash.h vars.c
  347.  
  348. bufs.o:    crash.h bufs.c
  349.  
  350. SHAR_EOF
  351. fi
  352. if test -f 'crash.c'
  353. then
  354.     echo shar: "will not over-write existing file 'crash.c'"
  355. else
  356. cat << \SHAR_EOF > 'crash.c'
  357. #include <sys/param.h>
  358. #include <sys/sysmacros.h>
  359. #include <sys/types.h>
  360. #include <sys/page.h>
  361. #include <sys/seg.h>
  362. #include <sys/proc.h>
  363. #include <sys/signal.h>
  364. #include <sys/dir.h>
  365. #include <sys/user.h>
  366. #include <sys/var.h>
  367. #include <sys/utsname.h>
  368. #include <fcntl.h>
  369. #include <stdio.h>
  370. #include "crash.h"
  371.  
  372. int    memfd;
  373. int    kmemfd;
  374. int    swapfd;
  375.  
  376. int    bflag;
  377. int    fflag;
  378. int    iflag;
  379. int    mflag;
  380. int    pflag;
  381. int    sflag;
  382. int    tflag;
  383. int    uflag;
  384. int    vflag;
  385.  
  386. int    anyflag;
  387.  
  388. struct    var    v;
  389. struct    file    *files;
  390. struct    inode    *inodes;
  391. struct    text    *texts;
  392. struct    proc    *procs;
  393. struct    mount    *mounts;
  394. struct    buf    *bufs;
  395. struct    buf    *bufstart;
  396. struct    user    user;
  397. daddr_t    swplo;
  398. struct    utsname    utsname;
  399. time_t    ktime;
  400. time_t    klbolt;
  401.  
  402. struct    xlist    namelist[] = {
  403.     { 0, 0, 0, "_v" },
  404.     { 0, 0, 0, "_file" },
  405.     { 0, 0, 0, "_inode" },
  406.     { 0, 0, 0, "_proc" },
  407.     { 0, 0, 0, "_text" },
  408.     { 0, 0, 0, "_mount" },
  409.     { 0, 0, 0, "_bufstrt" },
  410.     { 0, 0, 0, "_swplo" },
  411.     { 0, 0, 0, "_time" },
  412.     { 0, 0, 0, "_lbolt" },
  413.     { 0, 0, 0, "_utsname" },
  414.     { 0, 0, 0, "_u" },
  415.     { 0, 0, 0, (char *) 0 }
  416. };
  417.  
  418. usage ()
  419. {
  420.     fprintf (stderr, "usage: crash -bfimpstv [ -N namelist ] ");
  421.     fprintf (stderr, "[ -C corefile ] [ -S swapfile ]\n");
  422.     exit (1);
  423. }
  424.  
  425. r_read (fd, buf, n)
  426. int    fd;
  427. char    *buf;
  428. int    n;
  429. {
  430.     int    i;
  431.  
  432.     if ((i = read (fd, buf, n)) == -1) {
  433.         perror ("error on read");
  434.         return (-1);
  435.     } else
  436.         return (i);
  437. }
  438.  
  439. long    l_lseek (fd, offs, whence)
  440. int    fd;
  441. long    offs;
  442. int    whence;
  443. {
  444.     long    i;
  445.     long    lseek ();
  446.  
  447.     if ((i = lseek (fd, offs, whence)) == -1L) {
  448.         perror ("error on lseek");
  449.         return (-1);
  450.     } else
  451.         return (i);
  452. }
  453.  
  454. main (argc, argv)
  455. int    argc;
  456. char    **argv;
  457. {
  458.     char    newname[10];
  459.     char    *namefile = "/xenix";
  460.     char    *corefile = "/dev/mem";
  461.     char    *kmemfile = "/dev/kmem";
  462.     char    *swapfile = "/dev/swap";
  463.     int    c;
  464.     extern    int    optind;
  465.     extern    char    *optarg;
  466.  
  467.     setbuf (stdout, NULL);
  468.     setbuf (stderr, NULL);
  469.  
  470.     while ((c = getopt (argc, argv, "bfimpstuvN:C:S:")) != EOF) {
  471.         switch (c) {
  472.             case 'b':
  473.                 bflag++;
  474.                 anyflag++;
  475.                 break;
  476.             case 'C':
  477.                 corefile = optarg;
  478.                 kmemfile = optarg;
  479.                 break;
  480.             case 'f':
  481.                 fflag++;
  482.                 anyflag++;
  483.                 break;
  484.             case 'i':
  485.                 iflag++;
  486.                 anyflag++;
  487.                 break;
  488.             case 'm':
  489.                 mflag++;
  490.                 anyflag++;
  491.                 break;
  492.             case 'N':
  493.                 namefile = optarg;
  494.                 break;
  495.             case 'p':
  496.                 pflag++;
  497.                 anyflag++;
  498.                 break;
  499.             case 's':
  500.                 sflag++;
  501.                 anyflag++;
  502.                 break;
  503.             case 'S':
  504.                 swapfile = optarg;
  505.                 break;
  506.             case 't':
  507.                 tflag++;
  508.                 anyflag++;
  509.                 break;
  510.             case 'u':
  511.                 uflag++;
  512.                 anyflag++;
  513.                 break;
  514.             case 'v':
  515.                 vflag++;
  516.                 anyflag++;
  517.                 break;
  518.             default:
  519.                 usage ();
  520.         }
  521.     }
  522.     if (xlist (namefile, namelist) != 0) {
  523.         perror ("pstat: namelist");
  524.         exit (1);
  525.     }
  526.     if ((memfd = open (corefile, O_RDONLY)) < 0) {
  527.         perror ("pstat: corefile");
  528.         exit (1);
  529.     }
  530.     if ((kmemfd = open (kmemfile, O_RDONLY)) < 0) {
  531.         perror ("pstat: kmemfile");
  532.         exit (1);
  533.     }
  534.     if ((swapfd = open (swapfile, O_RDONLY)) < 0) {
  535.         perror ("pstat: swapfile");
  536.         exit (1);
  537.     }
  538.     l_lseek (kmemfd, namelist[NM_V].xl_value, 0);
  539.     r_read (kmemfd, &v, sizeof v);
  540.     l_lseek (kmemfd, namelist[NM_SWPLO].xl_value, 0);
  541.     r_read (kmemfd, &swplo, sizeof swplo);
  542.  
  543.     if (bflag)
  544.         prbufs ((int *) 0, 0);
  545.  
  546.     if (fflag)
  547.         prfiles ((int *) 0, 0);
  548.  
  549.     if (iflag)
  550.         prinodes ((int *) 0, 0);
  551.  
  552.     if (mflag) 
  553.         prmounts ((int *) 0, 0);
  554.  
  555.     if (pflag)
  556.         prprocs ((int *) 0, 0);
  557.  
  558.     if (sflag)
  559.         prstats ((int *) 0, 0);
  560.  
  561.     if (tflag)
  562.         prtexts ((int *) 0, 0);
  563.  
  564.     if (uflag)
  565.         prusers ((int *) 0, 0);
  566.  
  567.     if (vflag)
  568.         prvars ((int *) 0, 0);
  569.  
  570.     if (! anyflag) {
  571.         interact ();
  572.         exit (0);
  573.     } else {
  574.         exit (0);
  575.     }
  576. }
  577. SHAR_EOF
  578. fi
  579. if test -f 'interact.c'
  580. then
  581.     echo shar: "will not over-write existing file 'interact.c'"
  582. else
  583. cat << \SHAR_EOF > 'interact.c'
  584. #include <stdio.h>
  585. #include <string.h>
  586. #include <ctype.h>
  587. #include <setjmp.h>
  588. #include <signal.h>
  589.  
  590. extern    prbufs ();
  591. extern    prfiles ();
  592. extern    prinodes ();
  593. extern    prmounts ();
  594. extern    prprocs ();
  595. extern    prstats ();
  596. extern    prtexts ();
  597. extern    prusers ();
  598. extern    prvars ();
  599. extern    quit ();
  600. extern    help ();
  601. extern    int    errno;
  602.  
  603. jmp_buf    del;
  604. int    delflag;
  605.  
  606. struct    func {
  607.     void    (*f_func)();
  608.     char    *f_name;
  609. };
  610.  
  611. struct    func    commands[] = {
  612.     { prbufs, "b" },
  613.     { prbufs, "buf" },
  614.     { prfiles, "f" },
  615.     { prfiles, "file" },
  616.     { help, "h" },
  617.     { help, "help" },
  618.     { prinodes, "i" },
  619.     { prinodes, "ino" },
  620.     { prinodes, "inode" },
  621.     { prmounts, "m" },
  622.     { prmounts, "mount" },
  623.     { prprocs, "p" },
  624.     { prprocs, "proc" },
  625.     { quit, "q" },
  626.     { quit, "quit" },
  627.     { prstats, "s" },
  628.     { prstats, "stat" },
  629.     { prtexts, "t" },
  630.     { prtexts, "text" },
  631.     { prusers, "u" },
  632.     { prusers, "user" },
  633.     { prvars, "v" },
  634.     { prvars, "var" },
  635.     { 0, 0 }
  636. };
  637.  
  638. help ()
  639. {
  640.     printf ("command summary\n\n");
  641.  
  642.     printf ("buf (b)        - buffer headers\n");
  643.     printf ("file (f)       - open files\n");
  644.     printf ("help (h,?)     - list commands\n");
  645.     printf ("inode (ino,i)  - active inodes\n");
  646.     printf ("mount (m)      - mounted file systems\n");
  647.     printf ("proc (p)       - active and defunct processes\n");
  648.     printf ("quit (q,^D)    - exit crash\n");
  649.     printf ("stat (s)       - crash statistics, age, time\n");
  650.     printf ("text (t)       - active and sticky bit text segments\n");
  651.     printf ("user (u)       - user page information\n");
  652.     printf ("var (v)        - tunable parameters\n");
  653. }
  654.  
  655. quit ()
  656. {
  657.     exit (0);
  658. }
  659.  
  660. interupt (sig)
  661. int    sig;
  662. {
  663.     delflag = 1;
  664.     fflush (stdout);
  665.     fflush (stderr);
  666.     longjmp (del, sig);
  667. }
  668.  
  669. interact ()
  670. {
  671.     int    i;
  672.     int    items[100];
  673.     int    cnt;
  674.     char    *cp;
  675.     char    *com;
  676.     char    *num;
  677.     char    buf[BUFSIZ];
  678.  
  679.     while (setjmp (del))        /* catch that first interupt */
  680.         fprintf (stderr, "\nq to quit\n");
  681.  
  682.     signal (SIGINT, interupt);    /* and setup the handler */
  683.  
  684.     while (fprintf (stderr, "> "), gets (buf) != (char *) 0) {
  685.         while (setjmp (del))
  686.             goto eh;
  687.  
  688.         /*
  689.          * make all commands lower case.
  690.          */
  691.  
  692.         for (i = strlen (buf) - 1;i >= 0;i--)
  693.             if (isupper (buf[i]))
  694.                 buf[i] = tolower (buf[i]);
  695.  
  696.         /*
  697.          * find first non-white space character and skip if
  698.          * a blank line
  699.          */
  700.  
  701.         for (com = buf;*com && (*com == ' ' || *com == '\t');com++)
  702.             ;
  703.  
  704.         if (*com == '\0')
  705.             continue;
  706.  
  707.         /*
  708.          * find the entire command word
  709.          */
  710.  
  711.         if (*com == '?') {
  712.             help ();
  713.             continue;
  714.         }
  715.  
  716.         for (cp = com;*cp >= 'a' && *cp <= 'z';cp++)
  717.             ;
  718.  
  719.         if (*cp != '\0') {
  720.             *cp++ = '\0';
  721.  
  722.         /*
  723.          * tokenize the remainder of the string into numbers
  724.          */
  725.  
  726.             for (cnt = 0;*cp && cnt < 100;cnt++) {
  727.                 for (;*cp && isspace (*cp);cp++)
  728.                     ;
  729.  
  730.                 for (num = cp;*cp && isdigit (*cp);cp++)
  731.                     ;
  732.  
  733.                 if (*cp && ! isspace (*cp))
  734.                     goto eh;
  735.  
  736.                 if (*cp)
  737.                     *cp++ = '\0';
  738.  
  739.                 items[cnt] = atoi (num);
  740.             }
  741.         } else {
  742.             cnt = 0;
  743.         }
  744.         
  745.         for (i = 0;commands[i].f_name != (char *) 0;i++)
  746.             if (strcmp (commands[i].f_name, com) == 0)
  747.                 break;
  748.  
  749.         if (commands[i].f_name == (char *) 0)
  750.             goto eh;
  751.  
  752.         (*commands[i].f_func) (items, cnt);
  753.         continue;
  754.  
  755.         /*
  756.          * common error handler.  get here if an error is found.
  757.          */
  758. eh:
  759.         if (delflag) {
  760.             putc ('\n', stderr);
  761.             delflag = 0;
  762.         }
  763.         fprintf (stderr, "eh?\n");
  764.         signal (SIGINT, interupt);
  765.     }
  766. }
  767. SHAR_EOF
  768. fi
  769. if test -f 'files.c'
  770. then
  771.     echo shar: "will not over-write existing file 'files.c'"
  772. else
  773. cat << \SHAR_EOF > 'files.c'
  774. #include <sys/param.h>
  775. #include <sys/sysmacros.h>
  776. #include <sys/types.h>
  777. #include <sys/var.h>
  778. #include <sys/inode.h>
  779. #include <sys/file.h>
  780. #include <sys/page.h>
  781. #include <sys/seg.h>
  782. #include <sys/signal.h>
  783. #include <sys/dir.h>
  784. #include <sys/user.h>
  785. #include "crash.h"
  786.  
  787. prfiles (items, cnt)
  788. int    *items;
  789. int    cnt;
  790. {
  791.     int    i;
  792.  
  793.     files = (struct file *) malloc (v.v_file * sizeof (struct file));
  794.     l_lseek (kmemfd, namelist[NM_FILE].xl_value, 0);
  795.     r_read (kmemfd, files, sizeof (struct file) * v.v_file);
  796.  
  797.     printf ("SLOT    FLAG          COUNT  INODE      OFFSET\n");
  798.     if (cnt == 0) {
  799.         for (i = 0;i < v.v_file;i++) {
  800.             if (files[i].f_count == 0 || files[i].f_flag == 0)
  801.                 continue;
  802.  
  803.             dofile (i);
  804.         }
  805.     } else {
  806.         for (i = 0;i < cnt;i++) {
  807.             if (items[i] >= v.v_file)
  808.                 printf ("value (%d) out of range\n", items[i]);
  809.             else
  810.                 dofile (items[i]);
  811.         }
  812.     }
  813.     free ((char *) files);
  814. }
  815.  
  816.  
  817. dofile (i)
  818. int    i;
  819. {
  820.     printf ("%4d    %03o %c%c%c%c%c%c%c%c  %5d  %5d  %10ld\n",
  821.         i, files[i].f_flag & FMASK,
  822.         (files[i].f_flag & FREAD) ? 'R':' ',
  823.         (files[i].f_flag & FWRITE) ? 'W':' ',
  824.         (files[i].f_flag & FNDELAY) ? 'N':' ',
  825.         (files[i].f_flag & FAPPEND) ? 'A':' ',
  826.         (files[i].f_flag & FSYNC) ? 'S':' ',
  827.         (files[i].f_flag & FCREAT) ? 'C':' ',
  828.         (files[i].f_flag & FTRUNC) ? 'T':' ',
  829.         (files[i].f_flag & FEXCL) ? 'X':' ',
  830.         files[i].f_count,
  831.         files[i].f_inode - (struct inode *) namelist[NM_INODE].xl_value,
  832.         files[i].f_offset);
  833. }
  834. SHAR_EOF
  835. fi
  836. if test -f 'inodes.c'
  837. then
  838.     echo shar: "will not over-write existing file 'inodes.c'"
  839. else
  840. cat << \SHAR_EOF > 'inodes.c'
  841. #include <sys/param.h>
  842. #include <sys/sysmacros.h>
  843. #include <sys/types.h>
  844. #include <sys/var.h>
  845. #include <sys/inode.h>
  846. #include <a.out.h>
  847. #include "crash.h"
  848.  
  849. prinodes (items, cnt)
  850. int    *items;
  851. int    cnt;
  852. {
  853.     int    i;
  854.  
  855.     inodes = (struct inode *) malloc (v.v_inode * sizeof (struct inode));
  856.     l_lseek (kmemfd, namelist[NM_INODE].xl_value, 0);
  857.     r_read (kmemfd, inodes, sizeof (struct inode) * v.v_inode);
  858.  
  859.     printf ("SLOT MAJ  MIN INUMB REF LINK  UID  GID     SIZE    MODE SMAJ SMIN FLAGS\n");
  860.  
  861.     if (cnt == 0) {
  862.         for (i = 0;i < v.v_inode;i++) {
  863.             if (inodes[i].i_count == 0)
  864.                 continue;
  865.  
  866.             doinode (i);
  867.         }
  868.     } else {
  869.         for (i = 0;i < cnt;i++) {
  870.             if (items[i] >= v.v_inode)
  871.                 printf ("value (%d) out of range\n", items[i]);
  872.             else
  873.                 doinode (items[i]);
  874.         }
  875.     }
  876.     free ((char *) inodes);
  877. }
  878.     
  879. doinode (i)
  880. int    i;
  881. {
  882.     char    *modes = " pcCd bBf";
  883.     struct    inode    *ip;
  884.  
  885.     ip = &inodes[i];
  886.  
  887.     printf ("%4d %03o %04o %5d %3d %4d%5d%5d %8ld %c%c%c%c%03o",
  888.         i, major (ip->i_dev), minor (ip->i_dev), ip->i_number,
  889.         ip->i_count, ip->i_nlink, ip->i_uid, ip->i_gid,
  890.         ip->i_size,
  891.         modes[(ip->i_mode & IFMT) >> 12],
  892.         (ip->i_mode & ISUID) ? 'u':'-',
  893.         (ip->i_mode & ISGID) ? 'g':'-',
  894.         (ip->i_mode & ISVTX) ? 't':'-',
  895.         (ip->i_mode & 0777));
  896.  
  897.     if (! (((ip->i_mode & IFMT) == IFDIR) ||
  898.         ((ip->i_mode & IFMT) == IFREG) ||
  899.         ((ip->i_mode & IFMT) == IFIFO)))
  900.         printf (" %04o %04o", major (ip->i_rdev),
  901.                     minor (ip->i_rdev));
  902.     else
  903.         printf ("    -    -");    /* special file stuff */
  904.     if (ip->i_flag & IUPD)        printf (" upd");
  905.     if (ip->i_flag & IACC)        printf (" acc");
  906.     if (ip->i_flag & ICHG)        printf (" chg");
  907.     if (ip->i_flag & IMOUNT)    printf (" mnt");
  908.     if (ip->i_flag & ITEXT)        printf (" txt");
  909.     if (ip->i_flag & ILOCK)        printf (" lck");
  910. #ifdef    ISYN
  911.     if (ip->i_flag & ISYN)        printf (" syn");
  912. #endif
  913. #ifdef    IRMT
  914.     if (ip->i_flag & IRMT)        printf (" rmt");
  915. #endif
  916.     if (ip->i_flag & IWANT)        printf (" wnt");
  917.  
  918.     printf ("\n");
  919. }
  920. SHAR_EOF
  921. fi
  922. if test -f 'mounts.c'
  923. then
  924.     echo shar: "will not over-write existing file 'mounts.c'"
  925. else
  926. cat << \SHAR_EOF > 'mounts.c'
  927. #include <sys/param.h>
  928. #include <sys/sysmacros.h>
  929. #include <sys/types.h>
  930. #include <sys/var.h>
  931. #include <sys/inode.h>
  932. #include <sys/ino.h>
  933. #include <sys/buf.h>
  934. #include <sys/filsys.h>
  935. #include <sys/mount.h>
  936. #include <a.out.h>
  937. #include "crash.h"
  938.  
  939. prmounts (items, cnt)
  940. int    *items;
  941. int    cnt;
  942. {
  943.     int    i;
  944.  
  945.     mounts = (struct mount *) malloc (v.v_mount * sizeof (struct mount));
  946.     l_lseek (kmemfd, namelist[NM_MOUNT].xl_value, 0);
  947.     r_read (kmemfd, mounts, sizeof (struct mount) * v.v_mount);
  948.     l_lseek (kmemfd, namelist[NM_BUFFER].xl_value, 0);
  949.     r_read (kmemfd, &bufstart, sizeof bufstart);
  950.  
  951.     printf ("SLOT  MAJ  MIN  INODE  BUF  VOLUME  PACK   BLOCKS INODES  BFREE  IFREE\n");
  952.  
  953.     if (cnt == 0) {
  954.         for (i = 0;i < v.v_mount;i++) {
  955.             if (mounts[i].m_flags == 0)
  956.                 continue;
  957.  
  958.             domount (i);
  959.         }
  960.     } else {
  961.         for (i = 0;i < cnt;i++) {
  962.             if (items[i] >= v.v_mount)
  963.                 printf ("value (%d) out of range\n", items[i]);
  964.             else
  965.                 domount (items[i]);
  966.         }
  967.     }
  968.     free ((char *) mounts);
  969. }
  970.  
  971. domount (i)
  972. int    i;
  973. {
  974.     struct    filsys    filsys;
  975.     struct    buf    buf;
  976.     struct    inode    *ip = (struct inode *) namelist[NM_INODE].xl_value;
  977.  
  978.     printf ("%4d %4o  %03o %6d %4d",
  979.         i, major (mounts[i].m_dev), minor (mounts[i].m_dev),
  980.         mounts[i].m_inodp ?
  981.             mounts[i].m_inodp - ip : 0,
  982.         mounts[i].m_bufp ?
  983.             mounts[i].m_bufp - bufstart : 0);
  984.  
  985.     /*
  986.      * zero before using since unused mount entries don't have
  987.      * buffers and such.
  988.      */
  989.  
  990.     memset (&buf, 0, sizeof buf);
  991.     memset (&filsys, 0, sizeof filsys);
  992.  
  993.     if (mounts[i].m_flags != 0) {
  994.         l_lseek (memfd, (long) mounts[i].m_bufp, 0);
  995.         r_read (memfd, &buf, sizeof buf);
  996.         l_lseek (memfd, (long) buf.b_paddr, 0);
  997.         r_read (memfd, &filsys, sizeof filsys);
  998.     }
  999.     printf ("  %-6.6s  %-6.6s",
  1000.         filsys.s_fname, filsys.s_fpack);
  1001.  
  1002.     printf (" %6ld %6ld %6ld %6ld",
  1003.         filsys.s_fsize, INOPB * filsys.s_isize,
  1004.         (long) filsys.s_tfree, (long) filsys.s_tinode);
  1005.  
  1006.     putchar ('\n');
  1007. }
  1008. SHAR_EOF
  1009. fi
  1010. if test -f 'procs.c'
  1011. then
  1012.     echo shar: "will not over-write existing file 'procs.c'"
  1013. else
  1014. cat << \SHAR_EOF > 'procs.c'
  1015. #include <sys/param.h>
  1016. #include <sys/sysmacros.h>
  1017. #include <sys/types.h>
  1018. #include <sys/var.h>
  1019. #include <sys/text.h>
  1020. #include <sys/page.h>
  1021. #include <sys/seg.h>
  1022. #include <sys/proc.h>
  1023. #include <sys/signal.h>
  1024. #include <sys/dir.h>
  1025. #include <sys/user.h>
  1026. #include "crash.h"
  1027.  
  1028. /*
  1029.  * prprocs - output the process table
  1030.  */
  1031.  
  1032. prprocs (items, cnt)
  1033. int    *items;
  1034. int    cnt;
  1035. {
  1036.     struct    proc    *pp;
  1037.     struct    user    user;
  1038.     int    i;
  1039.  
  1040.     procs = (struct proc *) malloc (v.v_proc * sizeof (struct proc));
  1041.     lseek (kmemfd, namelist[NM_PROC].xl_value, 0);
  1042.     read (kmemfd, procs, sizeof (struct proc) * v.v_proc);
  1043.  
  1044.     printf ("SLT ST  PID  PPID  PGRP   UID  EUID PRI CPU    EVENT NAME       FLAGS\n");
  1045.  
  1046.     if (cnt == 0) {
  1047.         for (i = 0;i < v.v_proc;i++) {
  1048.             if (procs[i].p_stat == 0)
  1049.                 continue;
  1050.  
  1051.             doproc (i);
  1052.         }
  1053.     } else {
  1054.         for (i = 0;i < cnt;i++) {
  1055.             if (items[i] >= v.v_proc)
  1056.                 printf ("value (%d) out of range\n", items[i]);
  1057.             else
  1058.                 doproc (items[i]);
  1059.         }
  1060.     }
  1061.     free ((char *) procs);
  1062. }
  1063.  
  1064. doproc (i)
  1065. int    i;
  1066. {
  1067.     struct    proc    *pp;
  1068.  
  1069.     pp = &procs[i];
  1070.  
  1071.     printf ("%3d %c %5d %5d %5d %5d %5d %3d %3d", i,
  1072.         " swriztBST"[pp->p_stat], pp->p_pid, pp->p_ppid,
  1073.         pp->p_pgrp, pp->p_uid, pp->p_suid,
  1074.         pp->p_pri & 0377, pp->p_cpu & 0377);
  1075.  
  1076.     if (pp->p_wchan)
  1077.         printf (" %8x", pp->p_wchan);
  1078.     else
  1079.         printf ("         ");
  1080.  
  1081.     if (pp->p_stat == SZOMB) {
  1082.         printf (" ZOMBIE    ");
  1083.     } else if (pp->p_flag & SSYS) {
  1084.         printf (" swapper   ");
  1085.     } else if (pp->p_stat != 0) {
  1086.         if (findu (pp, i, &user))
  1087.             printf (" %-10.10s", user.u_comm);
  1088.         else
  1089.             printf (" SWAPPED   ");
  1090.     } else {
  1091.         printf ("           ");
  1092.     }
  1093.     if (pp->p_stat == SRUN)        printf (" running");
  1094.     if (pp->p_stat == SZOMB)    printf (" zombie");
  1095.     if (pp->p_flag & SLOAD)        printf (" incore");
  1096.     else                printf (" swapped");
  1097.     if (pp->p_flag & SSYS)        printf (" sched");
  1098.     if (pp->p_flag & SLOCK)        printf (" locked");
  1099.     if (pp->p_flag & STRC)        printf (" traced");
  1100.     if (pp->p_flag & SWTED)        printf (" wanted");
  1101.     if (pp->p_flag & STEXT)        printf (" text");
  1102.     if (pp->p_flag & SSPART)    printf (" part-swap");
  1103.  
  1104.     printf ("\n");
  1105. }
  1106. SHAR_EOF
  1107. fi
  1108. if test -f 'texts.c'
  1109. then
  1110.     echo shar: "will not over-write existing file 'texts.c'"
  1111. else
  1112. cat << \SHAR_EOF > 'texts.c'
  1113. #include <sys/param.h>
  1114. #include <sys/sysmacros.h>
  1115. #include <sys/types.h>
  1116. #include <sys/var.h>
  1117. #include <sys/inode.h>
  1118. #include <sys/text.h>
  1119. #include <sys/page.h>
  1120. #include <sys/seg.h>
  1121. #include <sys/proc.h>
  1122. #include <a.out.h>
  1123. #include "crash.h"
  1124.  
  1125. prtexts (items, cnt)
  1126. int    *items;
  1127. int    cnt;
  1128. {
  1129.     int    i;
  1130.  
  1131.     texts = (struct text *) malloc (v.v_text * sizeof (struct text));
  1132.     lseek (kmemfd, namelist[NM_TEXT].xl_value, 0);
  1133.     read (kmemfd, texts, sizeof (struct text) * v.v_text);
  1134.  
  1135.     printf ("SLOT  INODE  REF  LDREF  PROC  SWAPLO+   SIZE  FLAGS\n");
  1136.  
  1137.     if (cnt == 0) {
  1138.         for (i = 0;i < v.v_text;i++) {
  1139.             if (texts[i].x_count == 0)
  1140.                 continue;
  1141.  
  1142.             dotext (i);
  1143.         }
  1144.     } else {
  1145.         for (i = 0;i < cnt;i++) {
  1146.             if (items[i] >= v.v_text)
  1147.                 printf ("value (%d) out of range\n", items[i]);
  1148.             else
  1149.                 dotext (items[i]);
  1150.         }
  1151.     }
  1152.     free ((char *) texts);
  1153. }
  1154.  
  1155. dotext (i)
  1156. int    i;
  1157. {
  1158.     struct    text    *tp;
  1159.     int    procnum;
  1160.  
  1161.     tp = &texts[i];
  1162.  
  1163.     if (tp->x_ccount > 0)
  1164.         procnum = tp->x_caddr -
  1165.             (struct proc *) namelist[NM_PROC].xl_value;
  1166.     else
  1167.         procnum = 0;
  1168.  
  1169.     printf ("%4d  %5d  %3d  %5d  %4d  %7d  %5d ", i,
  1170.         tp->x_iptr - (struct inode *) namelist[NM_INODE].xl_value,
  1171.         tp->x_count, tp->x_ccount, procnum,
  1172.         tp->x_daddr, tp->x_size);
  1173.  
  1174.     if (tp->x_flag & XTRC)        printf (" trace");
  1175.     if (tp->x_flag & XWRIT)        printf (" write");
  1176.     if (tp->x_flag & XLOAD)        printf (" loaded");
  1177.     if (tp->x_flag & XLOCK)        printf (" locked");
  1178.     if (tp->x_flag & XWANT)        printf (" wanted");
  1179.     if (tp->x_flag & XLARGE)    printf (" large");
  1180.     if (tp->x_flag & XFPU)        printf (" fpu");
  1181.  
  1182.     printf ("\n");
  1183. }
  1184. SHAR_EOF
  1185. fi
  1186. if test -f 'user.c'
  1187. then
  1188.     echo shar: "will not over-write existing file 'user.c'"
  1189. else
  1190. cat << \SHAR_EOF > 'user.c'
  1191. #include <sys/param.h>
  1192. #include <sys/sysmacros.h>
  1193. #include <sys/types.h>
  1194. #include <sys/page.h>
  1195. #include <sys/seg.h>
  1196. #include <sys/file.h>
  1197. #include <sys/proc.h>
  1198. #include <sys/signal.h>
  1199. #include <sys/dir.h>
  1200. #include <sys/user.h>
  1201. #include <sys/var.h>
  1202. #include <sys/lock.h>
  1203. #include "crash.h"
  1204.  
  1205. findu (proc, slot, user)
  1206. struct    proc    *proc;
  1207. int    slot;
  1208. struct    user    *user;
  1209. {
  1210.     struct    proc    *procs = (struct proc *) namelist[NM_PROC].xl_value;
  1211.     long    swapaddr;
  1212.     int    i;
  1213.  
  1214.     if ((proc->p_flag & (SSWAP|SSPART)) || ! (proc->p_flag & SLOAD)) {
  1215.         swapaddr = proc->p_addr[0].te_frameno * NBPC;
  1216.         l_lseek (swapfd, swapaddr, 0);
  1217.         r_read (swapfd, user, sizeof *user);
  1218.     } else {
  1219.         l_lseek (memfd, proc->p_addr[0].te_frameno * NBPC, 0);
  1220.         r_read (memfd, user, sizeof *user);
  1221.     }
  1222.     if (user->u_procp - procs == slot)
  1223.         return (1);
  1224.     else
  1225.         return (0);
  1226. }
  1227.  
  1228. prusers (items, cnt)
  1229. int    *items;
  1230. int    cnt;
  1231. {
  1232.     int    i;
  1233.  
  1234.     if (cnt == 0) {
  1235.         douser (-1);
  1236.         return (1);
  1237.     }
  1238.     for (i = 0;i < cnt;i++) {
  1239.         if (items[i] >= v.v_proc) {
  1240.             printf ("value (%d) out of range\n", items[i]);
  1241.             continue;
  1242.         } else {
  1243.             douser (items[i]);
  1244.         }
  1245.     }
  1246. }
  1247.  
  1248. douser (i)
  1249. {
  1250.     struct    file    *fp;
  1251.     struct    proc    proc;
  1252.     struct    proc    *pp;
  1253.     static    char    *segments[] = { "user", "system", "user i" };
  1254.     int    fileno;
  1255.  
  1256.     pp = (struct proc *) namelist[NM_PROC].xl_value;
  1257.     fp = (struct file *) namelist[NM_FILE].xl_value;
  1258.  
  1259.     if (i >= 0) {
  1260.         l_lseek (kmemfd, (long) &pp[i], 0);
  1261.         r_read (kmemfd, &proc, sizeof proc);
  1262.  
  1263.         if (! findu (&proc, i, &user))
  1264.             return (0);
  1265.     } else {
  1266.         l_lseek (kmemfd, namelist[NM_USER].xl_value, 0);
  1267.         r_read (kmemfd, &user, sizeof user);
  1268.     }
  1269.     printf ("PER PROCESS USER AREA:\n");
  1270.     printf ("USER ID's:    uid: %d, gid: %d, real uid: %d, real gid: %d\n",
  1271.         user.u_uid, user.u_gid, user.u_ruid, user.u_rgid);
  1272.     printf ("PROCESS TIMES:    user: %d, sys: %d, child user: %d, child sys: %d\n",
  1273.         user.u_utime, user.u_stime, user.u_cutime, user.u_cstime);
  1274.     printf ("PROCESS MISC:    proc slot: %d, cntrl tty: maj(%d) min(%d)\n",
  1275.         user.u_procp - pp, major (user.u_ttyd), minor (user.u_ttyd));
  1276.     printf ("IPC:        locks:%s%s%s%s%s\n",
  1277.         user.u_lock == UNLOCK ? " unlocked":"",
  1278.         user.u_lock & PROCLOCK ? " proc":"",
  1279.         user.u_lock & TXTLOCK ? " text":"",
  1280.         user.u_lock & DATLOCK ? " data":"",
  1281.         user.u_lock & HUGELOCK ? " huge":"");
  1282.     printf ("FILE I/O:    user addr: %ld, file offset: %ld, bytes: %ld,\n",
  1283.         user.u_baseu, user.u_offset, user.u_count);
  1284.     printf ("        segment: %s, umask: %01o, ulimit: %ld\n",
  1285.         segments[user.u_segflg], user.u_cmask, user.u_limit);
  1286.     printf ("ACCOUNTING:    command: %s, memory: %ld, type: %s\n",
  1287.         user.u_comm, user.u_mem, user.u_acflag ? "fork":"exec");
  1288.     printf ("        start: %s",
  1289.         ctime (&user.u_start));
  1290.  
  1291.     printf ("OPEN FILES:    file desc:  ");
  1292.     for (i = 0;i < NOFILE;i++)
  1293.         if (user.u_ofile[i] != (struct file *) 0)
  1294.             printf ("%4d", i);
  1295.     putchar ('\n');
  1296.     
  1297.     printf ("        file slot:  ");
  1298.     for (i = 0;i < NOFILE;i++)
  1299.         if (user.u_ofile[i] != (struct file *) 0)
  1300.             printf ("%4d", user.u_ofile[i] - fp);
  1301.     putchar ('\n');
  1302.  
  1303.     return (0);
  1304. }
  1305. SHAR_EOF
  1306. fi
  1307. if test -f 'vars.c'
  1308. then
  1309.     echo shar: "will not over-write existing file 'vars.c'"
  1310. else
  1311. cat << \SHAR_EOF > 'vars.c'
  1312. #include <sys/param.h>
  1313. #include <sys/sysmacros.h>
  1314. #include <sys/types.h>
  1315. #include <sys/file.h>
  1316. #include <sys/inode.h>
  1317. #include <sys/page.h>
  1318. #include <sys/seg.h>
  1319. #include <sys/proc.h>
  1320. #include <sys/text.h>
  1321. #include <sys/mount.h>
  1322. #include <sys/var.h>
  1323. #include <a.out.h>
  1324. #include "crash.h"
  1325.  
  1326. prvars ()
  1327. {
  1328.     printf        ("buffers      %3d\n",
  1329.         v.v_buf);
  1330.     printf        ("calls      %3d\n",
  1331.         v.v_call);
  1332.     printf        ("inodes      %3d\n",
  1333.         v.v_inode);
  1334.     printf        ("e_inodes  %3d\n",
  1335.         v.ve_inode - (struct inode *) namelist[NM_INODE].xl_value);
  1336.     printf        ("files      %3d\n",
  1337.         v.v_file);
  1338.     printf        ("e_files      %3d\n",
  1339.         v.ve_file - (struct file *) namelist[NM_FILE].xl_value);
  1340.     printf        ("mounts      %3d\n",
  1341.         v.v_mount);
  1342.     printf        ("e_mounts  %3d\n",
  1343.         v.ve_mount - (struct mount *) namelist[NM_MOUNT].xl_value);
  1344.     printf        ("procs      %3d\n",
  1345.         v.v_proc);
  1346.     printf        ("e_procs      %3d\n",
  1347.         v.ve_proc - (struct proc *) namelist[NM_PROC].xl_value);
  1348.     printf        ("texts      %3d\n",
  1349.         v.v_text);
  1350.     printf        ("e_texts      %3d\n",
  1351.         v.ve_text - (struct text *) namelist[NM_TEXT].xl_value);
  1352.     printf        ("clists      %3d\n",
  1353.         v.v_clist);
  1354.     printf        ("sabufs      %3d\n",
  1355.         v.v_sabuf);
  1356.     printf        ("maxproc      %3d\n",
  1357.         v.v_maxup);
  1358. /*
  1359. swapmap      105
  1360. */
  1361.     printf        ("hashbuf      %3d\n",
  1362.         v.v_hbuf);
  1363.     printf        ("hashmask  %3d\n",
  1364.         v.v_hmask);
  1365. }
  1366. SHAR_EOF
  1367. fi
  1368. if test -f 'stats.c'
  1369. then
  1370.     echo shar: "will not over-write existing file 'stats.c'"
  1371. else
  1372. cat << \SHAR_EOF > 'stats.c'
  1373. #include <sys/param.h>
  1374. #include <sys/sysmacros.h>
  1375. #include <sys/types.h>
  1376. #include <sys/utsname.h>
  1377. #include <sys/param.h>
  1378. #include <a.out.h>
  1379. #include <time.h>
  1380. #include "crash.h"
  1381.  
  1382. #define    MINUTE    (60L)
  1383. #define    HOUR    (MINUTE*60L)
  1384. #define    DAY    (HOUR*24L)
  1385.  
  1386. prstats ()
  1387. {
  1388.     l_lseek (kmemfd, namelist[NM_UTSNAME].xl_value, 0);
  1389.     r_read (kmemfd, &utsname, sizeof utsname);
  1390.  
  1391.     l_lseek (kmemfd, namelist[NM_TIME].xl_value, 0);
  1392.     r_read (kmemfd, &ktime, sizeof ktime);
  1393.  
  1394.     l_lseek (kmemfd, namelist[NM_LBOLT].xl_value, 0);
  1395.     r_read (kmemfd, &klbolt, sizeof klbolt);
  1396.  
  1397.     printf ("    sysname: %.*s\n",
  1398.         sizeof utsname.sysname, utsname.sysname);
  1399.     printf ("    nodename: %.*s\n",
  1400.         sizeof utsname.nodename, utsname.nodename);
  1401.     printf ("    release: %.*s\n",
  1402.         sizeof utsname.release, utsname.release);
  1403.     printf ("    version: %.*s\n",
  1404.         sizeof utsname.version, utsname.version);
  1405.     printf ("    machine: %.*s\n",
  1406.         sizeof utsname.machine, utsname.machine);
  1407.  
  1408.     printf ("    time of crash: %s", ctime (&ktime));
  1409.  
  1410.     klbolt /= HZ;            /* convert to seconds */
  1411.  
  1412.     printf ("    age of system:");
  1413.  
  1414.     if (klbolt >= DAY)
  1415.         printf (" %d %s,", klbolt / DAY,
  1416.             klbolt >= (2*DAY) ? "days":"day");
  1417.  
  1418.     klbolt %= DAY;
  1419.  
  1420.     if (klbolt >= HOUR)
  1421.         printf (" %d %s,", klbolt / HOUR,
  1422.             klbolt >= (2*HOUR) ? "hrs.":"hr.");
  1423.  
  1424.     klbolt %= HOUR;
  1425.     klbolt /= MINUTE;
  1426.  
  1427.     printf (" %d %s\n", klbolt,
  1428.         klbolt == 0 || klbolt >= 2 ? "mins.":"min.");
  1429. }
  1430. SHAR_EOF
  1431. fi
  1432. if test -f 'bufs.c'
  1433. then
  1434.     echo shar: "will not over-write existing file 'bufs.c'"
  1435. else
  1436. cat << \SHAR_EOF > 'bufs.c'
  1437. #include <sys/param.h>
  1438. #include <sys/sysmacros.h>
  1439. #include <sys/types.h>
  1440. #include <sys/var.h>
  1441. #include <sys/inode.h>
  1442. #include <sys/ino.h>
  1443. #include <sys/buf.h>
  1444. #include <a.out.h>
  1445. #include "crash.h"
  1446.  
  1447. prbufs (items, cnt)
  1448. int    *items;
  1449. int    cnt;
  1450. {
  1451.     int    i;
  1452.  
  1453.     bufs = (struct buf *) malloc (v.v_buf * sizeof (struct buf));
  1454.  
  1455.     l_lseek (kmemfd, namelist[NM_BUFFER].xl_value, 0);
  1456.     r_read (kmemfd, &bufstart, sizeof bufstart);
  1457.  
  1458.     l_lseek (memfd, bufstart, 0);
  1459.     r_read (memfd, bufs, v.v_buf * sizeof (struct buf));
  1460.  
  1461.     printf (" BUF MAJ  MIN    BLOCK FLAGS\n");
  1462.  
  1463.     if (cnt == 0) {
  1464.         for (i = 0;i < v.v_buf;i++) {
  1465.             if (bufs[i].b_flags == 0)
  1466.                 continue;
  1467.  
  1468.             dobuf (i);
  1469.         }
  1470.     } else {
  1471.         for (i = 0;i < cnt;i++) {
  1472.             if (items[i] >= v.v_buf)
  1473.                 printf ("value (%d) out of range\n", items[i]);
  1474.             else
  1475.                 dobuf (items[i]);
  1476.         }
  1477.     }
  1478.     free ((char *) bufs);
  1479. }
  1480.  
  1481. dobuf (i)
  1482. int    i;
  1483. {
  1484.     struct    buf    *bp;
  1485.  
  1486.     bp = &bufs[i];
  1487.  
  1488.     printf ("%4d %03.3o %04.4o %8d",
  1489.         i, major (bp->b_dev) & 0377, minor (bp->b_dev), bp->b_blkno);
  1490.  
  1491.     if (bp->b_flags & B_READ)    printf (" read");
  1492.     if (bp->b_flags & B_DONE)    printf (" done");
  1493.     if (bp->b_flags & B_ERROR)    printf (" error");
  1494.     if (bp->b_flags & B_BUSY)    printf (" busy");
  1495.     if (bp->b_flags & B_PHYS)    printf (" phys");
  1496.     if (bp->b_flags & B_MAP)    printf (" map");
  1497.     if (bp->b_flags & B_WANTED)    printf (" wanted");
  1498.     if (bp->b_flags & B_AGE)    printf (" age");
  1499.     if (bp->b_flags & B_ASYNC)    printf (" async");
  1500.     if (bp->b_flags & B_DELWRI)    printf (" delwri");
  1501.     if (bp->b_flags & B_OPEN)    printf (" open");
  1502.     if (bp->b_flags & B_STALE)    printf (" stale");
  1503.     if (bp->b_flags & B_NOCROSS)    printf (" nocross");
  1504.     if (bp->b_flags & B_FLUSH)    printf (" flush");
  1505.  
  1506.     putchar ('\n');
  1507. }
  1508. SHAR_EOF
  1509. fi
  1510. if test -f 'crash.h'
  1511. then
  1512.     echo shar: "will not over-write existing file 'crash.h'"
  1513. else
  1514. cat << \SHAR_EOF > 'crash.h'
  1515. extern    int    memfd;
  1516. extern    int    kmemfd;
  1517. extern    int    swapfd;
  1518.  
  1519. #define    NM_V    0
  1520. #define    NM_FILE    1
  1521. #define    NM_INODE    2
  1522. #define    NM_PROC    3
  1523. #define    NM_TEXT    4
  1524. #define    NM_MOUNT    5
  1525. #define    NM_BUFFER    6
  1526. #define    NM_SWPLO    7
  1527. #define    NM_TIME        8
  1528. #define    NM_LBOLT    9
  1529. #define    NM_UTSNAME    10
  1530. #define    NM_USER        11
  1531. #define    NM_NAMES    12
  1532.  
  1533. extern    struct    xlist    namelist[];
  1534. extern    struct    var    v;
  1535. extern    struct    file    *files;
  1536. extern    struct    inode    *inodes;
  1537. extern    struct    text    *texts;
  1538. extern    struct    proc    *procs;
  1539. extern    struct    mount    *mounts;
  1540. extern    struct    buf    *bufs;
  1541. extern    struct    buf    *bufstart;
  1542. extern    struct    user    user;
  1543. extern    daddr_t    swplo;
  1544. extern    time_t    ktime;
  1545. extern    time_t    klbolt;
  1546. extern    struct    utsname    utsname;
  1547. SHAR_EOF
  1548. fi
  1549. exit 0
  1550. #    End of shell archive
  1551.